查看原文
其他

【解惑】到底是"时间片"?还是"分时轮询"?

bug菌 最后一个bug 2021-01-31

1、简单聊一聊

    今天为大家推荐一首迈克非常经典的歌曲<You Are Not Alone>,直译歌名为你不是孤单一个人的意思,一首非常治愈的歌曲,迈克的作品包括歌曲和舞蹈应该算是一代人的记忆吧,特别是太空步伐更是具有标志性和独特性。

    好了,今天这篇文章主要是为了说明一下平时大家经常提及的"时间片"和"分时轮询"这两个名词,因为作者在很久之前发布过一篇文章<单片机常用程序框架之分时轮询(详注代码)>,最近一些小伙伴在微信中问道:时间片和分时轮询有区别吗?等等,解释了很多,可能很多小伙伴还是有点疑惑,于是作者这里发布一篇文章,顺便简单扩展一下该话题。

1、任务调度

    任务调度对于电子类或者自动化类专业小伙伴最早接触一般都是在接触RTOS后了,然而对于计算机相关专业的小伙伴应该在学《计算机操作系统》老师对这一块讲解的非常清楚了,包括一些性能指标的定义与计算等等,不过作者这里仅仅只针对RTOS进行讲解,大家感兴趣可以找一下操作系统的书籍更加深入学习。

    大家都知道我们的操作系统可以隐蔽底层实现,为用户提供API接口来供我们的应用程序服务,同时操作系统可以管理多个任务实现CPU的最大利用率,然而对于RTOS提供的最主要功能就是任务的调度来管理多个任务

    任务的调度简单一点的说就是确定任务该怎么执行的一种机制,这种涉及到策略的问题其实都可以归纳为算法问题,从而也就会出现了各种各样的任务调度算法,比如时间片轮转调度算法、优先级调度算法、短任务先行调度算法等等,当然肯定没有一种完美的调度算法,每种算法都有其特点,根据任务的自身特点匹配任务调度从而满足用户需求。

    然而对于目前大部分的RTOS都是采用一种可剥夺方式的优先级抢占内核调度算法,通过为每个任务设置一个优先级来标记任务的紧急程度,优先级高的任务获得优先占用CPU的权利,当高优先级任务执行完毕进而寻找次高优先级来执行。(同时也存在优先级翻转问题)有阅读过1-2种RTOS内核的小伙伴应该都有一种感受:"这不都一样吗?",确实除了系统中实现的方式和效率有所差异之外,基本上都大同小异,不过大家在学习的过程应该多问一下为什么这样设计?这样设计的好处是什么?会带来什么问题?有没有自己觉得更好的设计方案?等等之类的。

2、"先来先服务调度"与“前后台架构

1)先来先服务调度 

    先来先服务调度(FCFS: first come first service)该调度算法算是最简单的一种,先进入就绪的任务首先占用CPU被执行,而且是一种非抢占式的任务调度,非常类似于数据结构-队列的形式,一旦任务进入就绪状态便会进入FIFO就绪队列。

特点说明:
  • 任务调度主要是存在任务的切换过程,需要进行现场的保存等等处理,而对于先到先服务调度,任务是不可剥夺的,每次都需要先进来的任务执行完毕主动的放弃CPU,进而执行下一个等待的任务。所以这样短任务的执行需要等待长任务执行完毕以后才能进行运行,这样对短任务的实时性大大降低,同时整体性能上也不是太好。

2)先来先服务VS前后台架构 

    之前很多小伙伴认为前后台的顺序执行架构和分时轮询架构都属于先进先服务调度,这里作者为大家分析一下他们之间的区别和关联:

区别与关联:
  • 一般先来先服务调度都是通过任务主动休眠放弃CPU,然后从就绪队列取出新的任务进行执行,就绪FIFO里面的任务顺序是根据任务休眠时间结束的事件先后来进行排列的,如果我们能够控制FIFO中的任务排序便能够实现跟前后台顺序和分时轮询类似的效果。

  • 然而对于前后台分时轮询架构其实和先进先服务调度还是存在一个优先级的概念在里面的,虽然说两者都不能实现任务上的抢占,不过对于分时轮询架构存在任务间的抢占,举个例子如下图所示:

  • 一些小伙伴该问了,在使用前后台分时轮询没有使用设置优先级呀,怎么会有优先级的概念呢?通过看之前的架构程序你会发现,我们整个程序运行是存在顺序的,比如执行顺序为任务1-->任务2-->任务3依次排列,当任务1快执行完毕,而任务3定时任务已经准备就绪很久了,此时刚好任务2时间到进入就绪,此时对于前后台分时轮询是会先执行任务2,因为任务2在任务1代码后面,而对于先进先服务调度则还是会执行任务3,然后执行任务2。

  • 那么其实我们可以对前后台分时轮询进行队列改造,其实可以达到先进先服务类似的效果,同样两者都是不可被抢断,每个任务都能够有执行的机会。

3、时间片调度-(也叫RR调度)

    还记很久之前uC/OSIII没有出现的时候,uC/OSII并不支持同优先级任务的运行,很多小伙伴想办法改写调度机制,不过现在主流RTOS应该都支持时间片轮询调度。时间片轮询调度是一种非常公平的调度办法,系统中规定一个时间单元,同优先级的任务按照顺序执行该时间单元规定的时间,执行完一个时间片便会切换到其他任务再执行相同的时间单元,这样交替执行实现多任务。

解析一下:
  • 我们可以通过上面的图看到时间片调度就是根据时间单元轮流切换执行时间,这样看来时间片的长选择尤为关键,如果时间片过短,大部分的事件都浪费在了任务的切换上面,那么CPU的利用率较低;但是如果时间片时间过长又会导致该调度退化为类似于先进先服务调度模式,这样对于短任务的响应是大打折扣的。

  • 所以时间片调度机制属于一种抢占式调度机制,如果有n个任务进行时间片调度,如果时间片的时间为t,那么每个任务得到执行的时间不会超过(n-1)t,一定要注意的是这里仅仅是得到执行,并不是执行结束,如果任务能够在一个时间片内执行完毕,则可以认为得到执行并执行完毕。

  • 如果选择最优时间片呢?如果你想通过理论来进行计算的话就需要了解一下调度的性能指标比如完成时间,周转时间,带权时间,平均周转时间,平均带权周转时间等等,然后通过测试每个任务的执行时间来求出最优的时间片;不过在我们程序的运行中大部分运行时间都是动态的,且时间片的选择对我们的需求影响并不是特别大,只要不过分小或者过分大均合适,一般个人取值都是在任务切换时间的50~100倍之间进行取值,同时也会根据实际调试情况进行调整。

4、最后小结

    通过上面的知识介绍大家应该明白前后台分时轮询和时间片的差异和联系了吧,其实叫做什么名字作者觉得并不是那么重要,关键是大家要达成共识,并且了解其中的区别,对于任务调度算法其实还有很多,大家平时可以对目前的RTOS进行调度机制的改造,并且通过对应的测试指标获得各个算法的性能。

    好了,这里是公众号:“最后一个bug”,一个为大家打造的技术知识提升基地。同时非常感谢各位小伙伴的支持,我们下期精彩见!

推荐好文  点击蓝色字体即可跳转

【连载】重温C++之“重载”(第三篇)

 【经典】解析一个STM32在线升级实例(usart版本)

【典藏】深度剖析单片机程序的运行(C程序版) 

【重磅】剖析MCU的IAP升级软件设计(设计思路篇)

☞ C语言为什么一般不在.h中定义函数或者变量?(精华)

GUI必备知识之“告别”乱码(浅显易懂)

【典藏】大佬们都在用的结构体进阶小技巧

听说因为代码没"对齐"程序就奔了?(深度剖析)

【典藏】自制小型GUI界面框架(设计思想篇)

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存